#!/usr/bin/env python
#-*- coding:utf-8 -*-

import socket
import os
import signal
import sys

def init():
    global server
    global client
    server = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    server.bind(('', 53))
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)


def get_domain_from_query(data):
    domain = ""
    opcode = (ord(data[2]) >> 3) & 15   # Opcode bits
    if opcode == 0:                     # Standard query
        ini = 12
        lon = ord(data[ini])              #获取域名DNS请求
        while lon != 0:
            domain += data[ini+1:ini+lon+1] + '.'
            ini += lon+1
            lon = ord(data[ini])
    return domain

RESPONSE_DATA_SAMPLE = '\xf9\xb7\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\x03www\x08facebook\x03com\x00\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x15U\x00\x04;\x18\x03\xad'
def get_ip_from_response(data):
    ip = ""
    rcode = ord(data[3]) & 15
    if rcode == 0:
        tag_pos = 12
        tag_len = ord(data[tag_pos])
        while tag_len != 0:
            tag_pos += tag_len+1
            tag_len = ord(data[tag_pos])
        tag_pos += tag_len+5
        if ord(data[tag_pos]) == 192:
            tag_pos += 11
            if ord(data[tag_pos]) == 4:
                tag_pos += 1
                ip = str(ord(data[tag_pos])) + '.' + str(ord(data[tag_pos + 1])) + '.' +str(ord(data[tag_pos + 2])) + '.' +str(ord(data[tag_pos + 3]));
    return ip

def is_in_GFW_ip_list(ip):
    GFW_list = list()
    GFW_list.append('1.1.1.1')
    if ip in GFW_list:
        return True
    return False

def is_in_GFW_domain_list(domain):
    GFW_list = list()
    GFW_list.append('appspot.com')
    for i in GFW_list:
        if domain.find(i) > -1:
            return True
    return False
 
if __name__ == '__main__':
    init()
    while True:
        data, ip = server.recvfrom(4096)
        signal.signal(signal.SIGCHLD, signal.SIG_IGN)
        if os.fork() == 0:
            try:
                domain = get_domain_from_query(data)
                client.settimeout(5)
                if is_in_GFW_domain_list(domain):
                    client.sendto(data, ('8.8.8.8', 53))
                else:
                    client.sendto(data, ('10.81.0.231', 53))
                response = client.recv(4096)
                print get_ip_from_response(response)
                server.sendto(response, ip)
            except:
                pass
            os._exit(0)
    
